package net.freebytes.test;


import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.UnsupportedEncodingException;

public abstract class InsGene extends BytesOps {
	protected byte[] ins = new byte[0];
	private byte[] escIns = new byte[0];

	private byte[] stx;
	private byte[] etx;

	private String encoding = "GBK";


	protected InsGene subInsGene = null;



	public void append(InsGene insGene){
		add(insGene.finalIns());
	}

	protected void initSubInsGeneAsEmpty(){
		subInsGene = new InsGene() {

			@Override
			public void escape() {
				// TODO Auto-generated method stub

			}

			@Override
			public byte[] checkCode() {
				// TODO Auto-generated method stub
				return null;
			}
		};
	}

	public void clear() {
		ins = new byte[0];
		escIns = new byte[0];
	}

	public void addHex(String subIns) {
		try {
			add(HEXCONV.toBytes(subIns));
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	protected byte[] short2Bytes(short length) {
		byte[] bLocalArr = new byte[2];

		for (int i = 0; i < 2; i++) {
			bLocalArr[1 - i] = (byte) (length >> 8 * i & 0xFF);
		}
		return bLocalArr;
	}

	private byte[] int2Bytes(int length) {
		byte[] bLocalArr = new byte[4];

		for (int i = 0; i < 4; i++) {
			bLocalArr[3 - i] = (byte) (length >> 8 * i & 0xFF);
		}
		return bLocalArr;
	}

	private byte[] long2Bytes(long length) {
		byte[] bLocalArr = new byte[8];

		for (int i = 0; i < 8; i++) {
			bLocalArr[7 - i] = (byte) (length >> 8 * i & 0xFF);
		}
		return bLocalArr;
	}

	public void addShort(short subIns) {
		try {
			add(short2Bytes(subIns));
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public void addInt(Integer subIns) {
		try {
			add(int2Bytes(subIns));
		} catch (Exception e) {
			e.printStackTrace();
		}
	}



	public void addLong(Long subIns) {
		try {
			add(long2Bytes(subIns));
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public void add(byte[] subIns) {
		this.ins = connect(ins, subIns);
	}

	public void add(byte subIns) {
		add(new byte[] { subIns });
	}

	public void add(String subIns) {
		try {
			add(subIns.getBytes(encoding));
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
	}

	public void add(String subIns, int bytenum) {

		try {
			byte[] Temp1 = new byte[bytenum];
			byte[] Temp2 = subIns.getBytes(getEncoding());
			System.arraycopy(Temp2, 0, Temp1, 0, Temp2.length);
			add(Temp1);
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
	}

	public void setStx(byte[] head) {
		stx = isEmpty(head) ? stx : head;
	}

	public void setEtx(byte[] rear) {
		etx = isEmpty(rear) ? etx : rear;
	}

	public int getInsLength() {
		return ins.length;
	}

	public byte[] checkedIns() {
		return connect(ins, checkCode());
	}

	public byte[] escapedIns() {
		escIns = checkedIns();
		escape();
		return escIns;
	}

	public byte[] finalIns() {
		byte[] addStx = connect(stx, escapedIns());
		// System.out.println(connect(addStx, etx).length);
		return connect(addStx, etx);
	}

	public String asciiIns() {
		return new String(finalIns());
	}

	public String hexIns() {
		return HEXCONV.toHexString(finalIns());
	}

	protected void replaceAll(byte[] former, byte[] latter) {
		escIns = replaceAll(escIns, former, latter);
	}

	public String getEncoding() {
		return encoding;
	}

	public void setEncoding(String encoding) {
		this.encoding = encoding;
	}

	public String addRN(String insGene) {
		if (isEmpty(insGene)) {
			return "\r\n";
		}
		StringBuilder strbulider = new StringBuilder(insGene);
		strbulider.append("\r\n");
		return strbulider.toString();
	}

	private boolean isEmpty(String bytes) {
		return bytes == null || bytes.equals("");
	}

	public byte[] addRN(byte[] insGene) {
		byte[] result = new byte[insGene.length + 2];
		try {
			System.arraycopy(insGene.length, 0, result, 0, insGene.length);
			System.arraycopy("\r\n".getBytes(), 0, result, insGene.length, 2);
		} catch (Exception e) {
		}
		return result;
	}

	/**
	 * @param str
	 * @param length
	 *            把一串字符串按照 指定的长度分割成字符串数组
	 * @return
	 */
	public String[] getSections(String str, int length) {
		int section = str.length() / length + 1;
		String[] sections = new String[section];
		int i = 0;
		try {
			while (section - 1 > i) {
				sections[i] = str.substring(i * length, (i + 1) * length);
				i++;
			}
			sections[i] = str.substring(i * length);
		} catch (Exception e) {
		}
		return sections;
	}

	public byte[] fileToBuffer(String filePath) {
		byte[] buffer = null;
		try {
			File file = new File(filePath);
			FileInputStream fis = new FileInputStream(file);
			ByteArrayOutputStream bos = new ByteArrayOutputStream(1000);
			byte[] b = new byte[1000];
			int n;
			while ((n = fis.read(b)) != -1) {
				bos.write(b, 0, n);
			}
			fis.close();
			bos.close();
			buffer = bos.toByteArray();
		} catch (Exception e) {
		}
		return buffer;
	}

	public String fixLength(String str, int length) {

		int strLength = str.length();
		if (strLength < length) {
			String temp = null;
			try {
				temp = String.format("%" + length + "s", str).replace(' ', '0');
			} catch (Exception e) {
			}
			return temp;
		}
		if (strLength == length) {
			return str;
		}
		return str.substring(strLength - length, strLength);
	}

	public boolean checkValue(String str, int min, int max, int radix) {
		int value;
		try {
			value = Integer.parseInt(str, radix);
		} catch (NumberFormatException e) {
			return false;
		}
		return value >= min && value <= max;
	}

	public boolean checkValue(String str, int min, int max) {
		return checkValue(str, min, max, 10);
	}

	public byte[] getIns(){
		return ins;
	}

	public abstract byte[] checkCode();

	public abstract void escape();
}
